#pragma once
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <numeric>
#include "matrix.h"
#include <set>
#define HOMEDIRECTORY "C:\\Documents and Settings\\Administrator\\My Documents\\Visual Studio 2005\\Projects\\ImageLab\\ImageLab\\"
#define LOGSPACE 10
#define E 2.7182818284590452353602874713527
using namespace std;

struct _corpusunit
{
	string word;
	unsigned int frequency;
	unsigned int bin;
};

class CBasicFunction
{
public:
	CBasicFunction(void);
public:
	~CBasicFunction(void);
public:
	// From Mikhail:
	std::string IntToString (int num);							// Converts int to std::string
	CString IntToCString (int num);								// Converts int to CString
	std::string BoolToString (bool thisBool);					// Converts a bool to std::string
	CString BoolToCString (bool thisBool);						// Converts a bool to CString
	bool FileIsEmpty (std::string filePath);					// File is empty?
	unsigned CharsInFile (std::string filePath);				// Returns the number of chars in file
	std::string Truncate (std::string str, int numChars);		// Truncate the string with x chars from the right
	bool StrAlphaCompare(std::string str1, std::string str2);	// Is str1 before str2 ?

	//convert a double to string
	CString		douTostr(double str);
	//write the string to file with the filedialog named caption
	bool		stringToFile(CString str, CString caption);
	//calculate the euclian distance
	double		eDistance(double* data1, double* data2, int NumElement);
	//write the string to log file
	bool		WriteToLog(CString str);

//Conversion between vectors and pointers
	//Convert the data in a pointer into a vector
	vector<double> PointerToVector(double* doublepointer, unsigned int numberofdata);
	vector<vector<double>> PointerToVector(double** doublepointer, unsigned int sizex, unsigned sizey);
	//Convert the data in vector into a pointer
	double*	VectorToPointer(vector<double> doublevector, unsigned int& numberofdata);
	double*	VectorToPointer(vector<vector<double>> doublevector, unsigned int& numberofdata);
	double**	VectorToPointer(vector<vector<double>> doublevector, unsigned int& dimension1, unsigned int& dimension2);

	//search forward for a char at the nearest position
	//m_t: target; m_s: source; m_cur: current position; m_len: source length
	int			SearchForward(char m_t, char* m_s, int m_cur, int m_len);
	unsigned int	SearchForward(char target, const char* sourcestring, unsigned int currentposition,
					unsigned int sourcelength);
	//search backward for a char at the nearest position
	//m_t: target; m_s: source; m_cur: current position; m_len: source length
	int			SearchBackward(char m_t, char* m_s, int m_cur, int m_len);
	unsigned int	SearchBackward(char target, const char* sourcestring, unsigned int currentposition,
					unsigned int sourcelength);

	//sreach forward for a string at the nearest position
	//m_t: target; m_s: source string; m_cur: current pos; m_tlen: target length; m_slen: source length
	int			SearchStr(char* m_t, char* m_s, int m_cur, int m_tlen, int m_slen);
	unsigned int	SearchStr(const char* m_t, const char* m_s, unsigned int m_cur,
					unsigned int m_tlen, unsigned int m_slen);

	//convert a CString to char*
	char*		CStringToChar(CString str);

	//validate if the dot is a full stop
	bool		ValidateFullStop(int curpos, char* m_s, int m_slen);

	//conver a integer to char*
	char*		IntToChar(int m_source);

//math function
	//cubic weight function
	double		CubicWeight(double x);

//Linguistic processing
	//Read words from a string
	vector<string>	LoadWordsFromString(string sourcestring, vector<unsigned int>& wordfrequency);
	vector<string>	LoadWordsFromString(string sourcestring);
	//Validate if a char is a letter or not
	bool		IsLetter(char singlechar);
	//Locate the sentence
	void		LocateSentence(string sourcestring, string lowercasestring, string word,
				vector<string>& sentences);
	void		LocateSentence(string sourcestring, string word, vector<string>& sentences);
	//Do the collocation
	void		CollocationSentences(vector<string> sentences, string word, vector<string>& collocations,
				vector<vector<double>>& collocationfrequency, vector<double>& collocationsumfrequency,
				vector<double>& collocationspread);
	//Search forward a string for a fullstop
	string::size_type SearchForwardForStop(string sourcestring, string::size_type startposition);
	unsigned int	SearchForwardForStop(const char* sourcestring, unsigned int sourcelength, unsigned int startposition);
	//Search backward a string for a fullstop
	string::size_type SearchBackwardForStop(string sourcestring, string::size_type startposition);
	unsigned int	SearchBackwardForStop(const char* sourcestring, unsigned int sourcelength, unsigned int startposition);
	//Change all caps into lower cases
	string		ChangeToLowerCase(string sourcestring);
	//Convert a source string into words
	vector<string> StringToWords(string sourcestring);
	vector<string> StringToWords(string sourcestring, string wholeword);
	//Get the excluding list
	vector<string> GetExcludingList();
	//Get the TFIDF for each term
	vector<vector<double>> GetTFIDF(vector<string> words, vector<string> documents);
	//Analyse a set of documents using TFIDF
	void		AnalyseDocuments(vector<string> documents, vector<string>& words,
				vector<unsigned int>& wordfrequency,	vector<vector<double>>& tfidf);
	//Load BNC corpus
	void		LoadBNCCorpus(vector<string>& words, vector<unsigned int>& frequency,
				unsigned long& sumoffrequency);
	//Computer weirdness
	vector<double>	ComputerWeirdness(vector<string> words, vector<unsigned int> frequency);
	//Do collocations for a set of words
	vector<unsigned int>	Collocations(string sourcestring, vector<string> wordlist, 
				vector<string>& collocations, vector<vector<double>>& frequency,
				vector<double>& spread, vector<double>& sumfrequency);
	//Select key terms
	vector<string>	SelectKeyterms(vector<string> wordlist, vector<unsigned int> frequency,	vector<double> weirdness,
							unsigned int ignorefrequency = 5);
	//Find a word in string
	string::size_type	FindLastWordInString(string sourcestring, string word);
	string::size_type	FindLastWordInString(string sourcestring, string word, string::size_type start,
						string::size_type end);
	//Remove the enter character in a string
	void RemoveEnter(string &enterstring);
	//Open a text file and load the content into a string
	string LoadFromFile(string filepath);
	//Load corpus
	vector<_corpusunit> SetCorpus(string filepath);
	//Get linguistic features
	vector<double> GetLinguisticFeature(string sourcestring, vector<_corpusunit> corpus);

//data conversion
	//conver a double vector to char*
	char*		DoubleVectorToChar(double* m_Double, int m_DoubleSize, int m_Precision, char m_Separator, int* m_CharSize);
	//conver a double matrix to char*
	char*		DoubleMatrixToChar(double** m_Double, int m_DoubleX, int m_DoubleY, int m_Precision, char m_Separator, int* m_CharSize);
	//read double data from a string
	double*		CharToDoubleVector(char* m_Source, int m_SourceLength, char m_Separator, int* m_Converted);
	string		DoubleMatrixToString(double** doubledata, int xdimension, int ydimension, int precision, char separator);

//Others
	//Voting
	int			OnVoting(int* m_VotingData, int m_NumberVote, int m_DataLength);

//Loading data from files
	//Load data from a file name and return a double**
	double**	LoadDoubleFromFile(CString FileName, int* Rows, int* Columns);
	vector<vector<double> > LoadDoubleFromFile(string filename, string separator);
	//Get the dimension of the data
	bool		GetDataDimension(char* f_input, int f_len, int* d_column, int* d_row);
	//Read the data
	bool		ReadMatrixData(char* f_input, int f_len, int d_column, int d_row, double** m_data);

//File operation
	//Append the content to an existing file
	bool		AppendToFile(CString filename, CString m_content);
	//Write the data to a file, if existed, overwrite it
	bool		WriteToFile(CString filename, CString m_content);

//Matrix operation
	//transpose a matrix
	double**	matrixTransp(double** m_data, int m_column, int m_row);
	//normalize data by rows
	bool		normalizedData(double** un_data, int un_c, int un_r, double* n_ave, double* n_std);
	//generate a random double matrix
	double**	RandomDoubleMatrix(int m_c, int m_r);
	//Delete a matrix
	void		DeleteMatrix(double** input, int row);
	//Rescale a matrix
	void		MatrixRescale(double** input, int row, int column, double newmin, double newmax);
	//Get the max and min of a matrix
	void		MatrixMaxMin(double** input, int row, int column, double* maxvalue, double* minvalue);
	double**	MatrixInterpolation(double** input, int row, int column, int newrow, int newcolumn);

//Histogram operation
	double		GetOtsuThreshold(double* histogram, int sizeofhistogram);

//Vector operation
	//Get the max and min of a vector
	void		VectorMaxMin(double* input, int inputsize, double* maxvalue, double* minvalue);
	void		VectorRescale(double* input, int inputsize, double maxvalue, double minvalue);

//Load images from a folder including all the subfolders
	vector<string> LoadImagesFromAFolder(void);
	vector<string> LoadImagesFromAFolder(string folderpath);
//Popup a dialog to select multiple files
	vector<string> SelectMultipleFiles(CString stringfilter);
	vector<string> SelectMultipleFiles(CString stringfilter, CString dialogcaption);
//Select a folder
	string				SelectAFolder();
	vector<string>	GetFilesFromAFolder(string folder, string extension);

//Save data to binary file
	void		SaveDataAsBinary(vector<vector<vector<vector<double>>>> data, string filepath);
	void		SaveDataAsBinary(vector<vector<vector<double>>> data, string filepath);
	void		SaveDataAsBinary(vector<vector<double>> data, string filepath);
	void		SaveDataAsBinary(vector<double> data, string filepath);
	vector<vector<vector<double>>> LoadBinaryData(string filename);
	void		LoadBinaryData(vector<vector<double>>& data, string filename);
	void		LoadBinaryData(vector<vector<vector<vector<double>>>>& data, string filename);
	void		LoadBinaryData(vector<double>& data, string filename);
//Load DICOM
	unsigned int		LoadDICOM(vector<unsigned char> datasource, unsigned int& imageheight, unsigned int& imagewidth,
		vector<unsigned char>& imagedata, string& bitdepth);
};
